import tkinter as tk
from tkinter import filedialog, ttk, messagebox
import threading
from PIL import Image
import os
import sys
import glob


def gif_to_png_sequence(gif_path, output_dir=None, prefix=None, update_callback=None):
    """将单个GIF文件转换为PNG序列"""
    # 检查文件是否存在
    if not os.path.exists(gif_path):
        message = f"错误: 文件 '{gif_path}' 不存在"
        if update_callback:
            update_callback(message)
        return False

    # 获取GIF文件名和目录
    gif_dir = os.path.dirname(gif_path) or "."
    gif_filename = os.path.basename(gif_path)
    gif_name = os.path.splitext(gif_filename)[0]

    # 设置默认输出目录和前缀
    if not output_dir:
        output_dir = os.path.join(gif_dir, f"{gif_name}_frames")
    if not prefix:
        prefix = gif_name

    # 创建输出目录
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)

    try:
        # 打开GIF文件
        with Image.open(gif_path) as img:
            frame_count = 0
            # 循环遍历所有帧
            while True:
                try:
                    # 保存当前帧为PNG
                    current_frame = img.convert('RGBA')
                    output_filename = f"{prefix}_{frame_count:03d}.png"
                    output_path = os.path.join(output_dir, output_filename)
                    current_frame.save(output_path)

                    if update_callback:
                        update_callback(f"已保存: {output_filename}")

                    # 获取下一帧
                    frame_count += 1
                    img.seek(frame_count)
                except EOFError:
                    # 到达GIF文件末尾
                    break

        message = f"转换完成: '{gif_path}' -> {frame_count} 帧图像保存到 '{output_dir}'"
        if update_callback:
            update_callback(message)
        return True

    except Exception as e:
        message = f"转换过程中发生错误: {e}"
        if update_callback:
            update_callback(message)
        return False


def batch_convert_gifs(gif_paths, output_base_dir=None, update_callback=None):
    """批量转换多个GIF文件为PNG序列"""
    success_count = 0
    fail_count = 0

    for gif_path in gif_paths:
        # 对每个GIF文件，如果指定了基础输出目录，则在其下创建子目录
        if output_base_dir:
            gif_name = os.path.splitext(os.path.basename(gif_path))[0]
            output_dir = os.path.join(output_base_dir, gif_name)
        else:
            output_dir = None

        if update_callback:
            update_callback(f"开始处理: '{gif_path}'")

        result = gif_to_png_sequence(gif_path, output_dir, None, update_callback)
        if result:
            success_count += 1
        else:
            fail_count += 1

    message = f"\n批量转换完成！成功: {success_count}, 失败: {fail_count}"
    if update_callback:
        update_callback(message)


class GifToPngApp:
    def __init__(self, root):
        self.root = root
        self.root.title("GIF转PNG序列工具")
        self.root.geometry("600x500")
        self.root.resizable(True, True)

        self.selected_files = []
        self.output_dir = ""

        self.create_widgets()

    def create_widgets(self):
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 文件选择区域
        file_frame = ttk.LabelFrame(main_frame, text="选择GIF文件", padding="10")
        file_frame.pack(fill=tk.X, pady=5)

        self.file_list = tk.Listbox(file_frame, height=5)
        self.file_list.pack(fill=tk.X, side=tk.LEFT, expand=True)

        file_scroll = ttk.Scrollbar(file_frame, orient=tk.VERTICAL, command=self.file_list.yview)
        file_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        self.file_list.config(yscrollcommand=file_scroll.set)

        # 文件选择按钮
        btn_frame = ttk.Frame(main_frame)
        btn_frame.pack(fill=tk.X, pady=5)

        ttk.Button(btn_frame, text="选择文件", command=self.select_files).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="选择目录", command=self.select_directory).pack(side=tk.LEFT, padx=5)
        ttk.Button(btn_frame, text="清除列表", command=self.clear_files).pack(side=tk.LEFT, padx=5)

        # 输出设置区域
        output_frame = ttk.LabelFrame(main_frame, text="输出设置", padding="10")
        output_frame.pack(fill=tk.X, pady=5)

        ttk.Label(output_frame, text="输出目录:").grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
        self.output_path_var = tk.StringVar()
        ttk.Entry(output_frame, textvariable=self.output_path_var, width=50).grid(row=0, column=1, sticky=tk.EW, padx=5,
                                                                                  pady=5)
        ttk.Button(output_frame, text="浏览", command=self.select_output_dir).grid(row=0, column=2, padx=5, pady=5)

        ttk.Label(output_frame, text="文件前缀:").grid(row=1, column=0, sticky=tk.W, padx=5, pady=5)
        self.prefix_var = tk.StringVar()
        ttk.Entry(output_frame, textvariable=self.prefix_var, width=50).grid(row=1, column=1, sticky=tk.EW, padx=5,
                                                                             pady=5)
        ttk.Label(output_frame, text="(可选)").grid(row=1, column=2, padx=5, pady=5)

        output_frame.columnconfigure(1, weight=1)

        # 转换按钮
        ttk.Button(main_frame, text="开始转换", command=self.start_conversion).pack(pady=10)

        # 进度显示区域
        log_frame = ttk.LabelFrame(main_frame, text="转换日志", padding="10")
        log_frame.pack(fill=tk.BOTH, expand=True, pady=5)

        self.log_text = tk.Text(log_frame, height=10, wrap=tk.WORD)
        self.log_text.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)

        log_scroll = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.log_text.yview)
        log_scroll.pack(side=tk.RIGHT, fill=tk.Y)
        self.log_text.config(yscrollcommand=log_scroll.set)

        # 状态栏
        self.status_var = tk.StringVar(value="就绪")
        status_bar = ttk.Label(self.root, textvariable=self.status_var, relief=tk.SUNKEN, anchor=tk.W)
        status_bar.pack(side=tk.BOTTOM, fill=tk.X)

    def select_files(self):
        filetypes = [("GIF文件", "*.gif"), ("所有文件", "*.*")]
        files = filedialog.askopenfilenames(filetypes=filetypes, title="选择GIF文件")
        if files:
            for file in files:
                if file.lower().endswith('.gif') and file not in self.selected_files:
                    self.selected_files.append(file)
                    self.file_list.insert(tk.END, os.path.basename(file))

            self.status_var.set(f"已选择 {len(self.selected_files)} 个文件")

    def select_directory(self):
        folder = filedialog.askdirectory(title="选择包含GIF文件的目录")
        if folder:
            gif_files = glob.glob(os.path.join(folder, "*.gif"))
            if gif_files:
                new_added = 0
                for file in gif_files:
                    if file not in self.selected_files:
                        self.selected_files.append(file)
                        self.file_list.insert(tk.END, os.path.basename(file))
                        new_added += 1

                self.status_var.set(f"从目录添加了 {new_added} 个GIF文件")
            else:
                messagebox.showinfo("提示", "所选目录中没有GIF文件")

    def select_output_dir(self):
        folder = filedialog.askdirectory(title="选择输出目录")
        if folder:
            self.output_dir = folder
            self.output_path_var.set(folder)

    def clear_files(self):
        self.selected_files = []
        self.file_list.delete(0, tk.END)
        self.status_var.set("已清除文件列表")

    def add_log(self, message):
        self.log_text.insert(tk.END, message + "\n")
        self.log_text.see(tk.END)
        self.root.update_idletasks()

    def start_conversion(self):
        if not self.selected_files:
            messagebox.showwarning("警告", "请先选择GIF文件")
            return

        output_dir = self.output_path_var.get().strip()
        prefix = self.prefix_var.get().strip()

        # 清空日志
        self.log_text.delete(1.0, tk.END)
        self.status_var.set("正在转换...")

        # 在新线程中运行转换，以保持UI响应
        def conversion_thread():
            self.add_log(f"开始转换 {len(self.selected_files)} 个GIF文件...")

            # 单文件且有前缀
            if len(self.selected_files) == 1 and prefix:
                gif_to_png_sequence(self.selected_files[0], output_dir, prefix, self.add_log)
            else:
                batch_convert_gifs(self.selected_files, output_dir, self.add_log)

            self.status_var.set("转换完成")

        threading.Thread(target=conversion_thread, daemon=True).start()


if __name__ == "__main__":
    root = tk.Tk()
    app = GifToPngApp(root)
    root.mainloop()